#include "preHeader.h"
#include "Session/PlayerPacketHandler.h"
#include "Map/MapInstance.h"
#include "tile/InrangeIterator.h"

bool Player::GetChatMessageThing(
	INetPacket& pck, int8 thingType, uint32 thingId) const
{
	switch (ChatThingType(thingType)) {
	case ChatThingType::Item:
		return GetChatMessageThing4Item(pck, thingId);
	default:
		return false;
	}
}

bool Player::GetChatMessageThing4Item(INetPacket& pck, uint32 itemSlot) const
{
	Item* pItem = m_pItemStorage->
		GetItem(ItemSlotType(itemSlot >> 24), itemSlot & 0xffffff);
	if (pItem == NULL) {
		return false;
	}
	pItem->GetItemProp().Save(pck);
	return true;
}

void Player::BuildClientChatMessagePacket(INetPacket& pck, ChannelType channelType,
	const std::string_view& strMsg, const std::string_view& strArgs) const
{
	pck.Reset(SMSG_CHAT_MESSAGE);
	pck << (s8)channelType << GetGuid() << GetName() << strMsg;
	pck.Append(strArgs.data(), strArgs.size());
}

GErrorCode Player::HandleChatMessage4Whisper(ObjGUID toGuid,
	const std::string_view& strMsg, const std::string_view& strArgs)
{
	auto pToChar = m_pMapInstance->GetAvailablePlayer(toGuid);
	if (pToChar == NULL) {
		return TargetNotExist;
	}

	NetPacket pack;
	BuildClientChatMessagePacket(pack, ChannelType::tWhisper, strMsg, strArgs);
	pToChar->SendPacket(pack);

	return CommonSuccess;
}

GErrorCode Player::HandleChatMessage4Speak(
	const std::string_view& strMsg, const std::string_view& strArgs)
{
	NetPacket pack;
	BuildClientChatMessagePacket(pack, ChannelType::tSpeak, strMsg, strArgs);

	InrangeIterator itr(&m_pMapInstance->sTileHandler,
		m_position.x, m_position.z, MAX_CHAT_SPEAK_DIST);
	itr.ForeachActor([&pack](TileActor* pActor) {
		auto pLObj = static_cast<LocatableObject*>(pActor);
		if (!pLObj->IsType(TYPE_PLAYER)) {
			return false;
		}
		auto pPlayer = static_cast<Player*>(pLObj);
		pPlayer->SendPacket(pack);
		return false;
	});

	return CommonSuccess;
}

int PlayerPacketHandler::HandleChatMessage(Player *pPlayer, INetPacket &pck)
{
	int8 channelType;
	ObjGUID toGuid;
	std::string_view strMsg;
	pck >> channelType >> toGuid >> strMsg;

	auto strArgs = pck.CastReadableStringView();

	GErrorCode errCode = CommonSuccess;
	switch (ChannelType(channelType)) {
	case ChannelType::tWhisper:
		errCode = pPlayer->HandleChatMessage4Whisper(toGuid, strMsg, strArgs);
		break;
	case ChannelType::tSpeak:
		errCode = pPlayer->HandleChatMessage4Speak(strMsg, strArgs);
		break;
	}
	if (errCode != CommonSuccess) {
		pPlayer->SendError(errCode);
	}

	return SessionHandleSuccess;
}
